package service

import (
	"context"
	"gitee.com/hxchjm/go-admin/internal/dao"
	"gitee.com/hxchjm/go-admin/internal/models"
	"gitee.com/hxchjm/go-admin/internal/pkg/captcha"
	"gitee.com/hxchjm/go-admin/pkg/ecode"
	"gitee.com/hxchjm/go-admin/pkg/jwtauth"
	"github.com/golang-jwt/jwt"
	"github.com/hxchjm/log"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
	"time"
)

const (
	JwtTokenExpire = time.Hour * 24
)

func Login(ctx context.Context, req *models.ReqLogin) (interface{}, error) {
	if req.UserName == "" || req.Password == "" {
		return nil, ecode.Wrap(ecode.ERRParam, "user or passwd is empty")
	}
	//校验验证码
	if !captcha.Verify(req.UUid, req.Code, true) {
		return nil, ecode.ERRCaptChaVerify
	}
	ui, ds, err := dao.SysUser{SysUser: models.SysUser{Username: req.UserName}}.GetUserInfo(ctx)
	if err != nil {
		return nil, err
	}
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, ecode.ERRLoginUserNotFound
		}
		log.Errorf(ctx, "query err (%+v)", err)
		return nil, err
	}
	if ui != nil && ui.UserId == 0 {
		log.Errorf(ctx, "not register")
		return nil, ecode.ErrLoginNotReg
	}

	//校验密码
	if err = bcrypt.CompareHashAndPassword([]byte(ui.Password), []byte(req.Password)); err != nil {
		return nil, ecode.ERRLoginPwdNotFound
	}
	ri, err := dao.SysRole{SysRole: models.SysRole{RoleId: ui.RoleId}}.Get(ctx)
	if err != nil {
		return nil, err
	}
	expireAt := time.Now().Add(JwtTokenExpire).Unix() // 签名的过期时间
	// 生成token
	customClaims := jwtauth.CustomClaims{
		UID:      ui.UserId,
		NickName: req.UserName,
		//RoleName: ri.RoleName,
		RoleKey:   ri.RoleKey,
		DataScope: ds,
		DeptId:    1,
		RoleId:    1,
		StandardClaims: jwt.StandardClaims{
			NotBefore: time.Now().Unix(), // 签名的生效时间
			ExpiresAt: expireAt,          // 签名的过期时间
			Issuer:    "sean",            // 签名颁发者
		},
	}

	//生成token
	j := jwtauth.NewJWT()
	token, err := j.GenerateToken(customClaims)
	if err != nil {
		return nil, ecode.ErrLoginGenKey
	}
	rsp := models.RspLogin{
		Token:  token,
		Expire: expireAt,
		Role:   ri.RoleName,
	}
	return rsp, nil
}

func Logout(ctx context.Context) (interface{}, error) {
	return nil, nil
}

func GenCaptcha(ctx context.Context) (interface{}, error) {
	id, b64s, err := captcha.DriverDigitFunc()
	if err != nil {
		log.Errorf(ctx, "DriverDigitFunc error, %s", err.Error())
		return nil, ecode.ERRCaptChaFetch
	}
	res := &models.RspCaptcha{
		Id:   id,
		Data: b64s,
	}
	return res, nil
}

// GetInfo
// @Summary 获取个人信息，包括权限信息
// @Description 获取JSON
// @Tags 个人中心
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/getinfo [get]
// @Security Bearer
func GetInfo(ctx context.Context) (interface{}, error) {
	claim := jwtauth.GetClaims(ctx)
	log.Infof(ctx, "claim is (%+v)", claim)
	rsp := &models.RspGetInfo{
		Avatar:      "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif",
		Buttons:     append([]string{}, "*:*:*"),
		Roles:       append([]string{}, claim.RoleKey),
		Permissions: append([]string{}, "*:*:*"),
	}
	if claim.RoleKey != "admin" {
		list, _ := dao.SysRole{SysRole: models.SysRole{RoleKey: claim.RoleKey}}.GetByKey(ctx)
		rsp.Permissions = list
		rsp.Buttons = list
	}

	su, err := dao.SysUser{SysUser: models.SysUser{UserId: claim.UID}}.Get(ctx)
	if err != nil {
		return nil, ecode.ERRLogin
	}
	if su.Avatar != "" {
		rsp.Avatar = su.Avatar
	}
	rsp.UserId = su.UserId
	rsp.UserName = su.Username
	rsp.Name = su.NickName
	rsp.DeptId = su.DeptId
	return rsp, nil
}

// GetRoleMenu 根据登录角色名称获取菜单列表数据（左菜单使用）
// @Summary 根据登录角色名称获取菜单列表数据（左菜单使用）
// @Description 获取JSON
// @Tags 菜单
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/menurole [get]
// @Security Bearer
func GetRoleMenu(ctx context.Context) (any, error) {
	claim := jwtauth.GetClaims(ctx)
	res, err := dao.SysMenu{}.GetRoleMenu(claim.RoleKey)
	if err != nil {
		return nil, err
	}
	return res, nil
}
